﻿using housingsafety.server.Caching.Core;
using housingsafety.server.Entities.DataModels;
using housingsafety.server.Helpers;
using housingsafety.server.Models;
using housingsafety.server.Repository;
using housingsafety.server.Security;
using housingsafety.server.Snowflake;
using housingsafety.server.Svcs;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Logging;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace housingsafety.server.Controllers
{
    /// <summary>
    /// 身份验证(OK)
    /// </summary>
    public class AuthenticationController : BaseController<AuthenticationController>
    {
        private readonly ISmsHelper _smsHelper;
        private readonly IAuthenticateService _authService;
        private readonly IRepository<ZmUser> _userRepository;
        private readonly ICache _cache;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="authService">授权接口</param>
        /// <param name="smsHelper">短信验证接口</param>
        /// <param name="userRepository">用户存储</param>
        /// <param name="cacheProvider"></param>
        /// <param name="logger">日志接口</param>
        /// <param name="systemLogRepository"></param>
        public AuthenticationController(IAuthenticateService authService
            , IRepository<ZmUser> userRepository
            , ICacheProvider cacheProvider
            , ISmsHelper smsHelper
            , ILogger<AuthenticationController> logger
            , IRepository<ZmSystemLog> systemLogRepository)
            : base(logger, systemLogRepository)
        {
            _cache = cacheProvider.CreateCache();
            _userRepository = userRepository;
            _authService = authService;
            _smsHelper = smsHelper;
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="request">请求参数</param>
        /// <returns>请求token</returns>
        [AllowAnonymous]
        [HttpPost("login/in")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<AuthenticateResponse>), 200)]
        public RespRet<AuthenticateResponse> Login([FromQuery] AuthenticateRequest request)
        {

            if (!ModelState.IsValid)
            {
                return new RespRet<AuthenticateResponse>(false, "Invalid Request");
            }

            if (string.IsNullOrEmpty(request.UserName))
            {
                return new RespRet<AuthenticateResponse>(false, "用户名必须输入");
            }

            var response = _authService.Authenticate(request, this.IpAddress());
            if (response == null)
            {
                return new RespRet<AuthenticateResponse>(false, "用户名或密码不正确");
            }

            if (response.Succ)
            {
                this.SetTokenCookie(response.Data.RefreshToken);
            }

            return response;
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        /// <returns></returns>
        [HttpPost("login/out")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet), 200)]
        public RespRet LoginOut()
        {
            // accept token from request body or cookie
            var token = this.CurrentUser() ?? Request.Cookies["refreshToken"];
            if (string.IsNullOrEmpty(token))
            {
                return new RespRet(false, "token is required");
            }

            var response = _authService.RevokeToken(token, this.IpAddress());
            if (!response.Succ)
            {
                return new RespRet(false, "token not found");
            }

            this.RemoveTokenCookie();
            return new RespRet(true, "token revoked");
        }

        /// <summary>
        /// 刷新Token
        /// </summary>
        /// <param name="model">刷新Token信息</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("tokens/refresh")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet<AuthenticateResponse>), 200)]
        public RespRet<AuthenticateResponse> RefreshToken([FromQuery] RefreshTokenRequest model)
        {
            var refreshToken = model.Token ?? Request.Cookies["refreshToken"];
            if (string.IsNullOrEmpty(refreshToken))
            {
                return new RespRet<AuthenticateResponse>(false, "refreshToken is required");
            }

            var response = _authService.RefreshToken(refreshToken, this.IpAddress());
            if (response == null)
            {
                return new RespRet<AuthenticateResponse>(false, "Invalid token");
            }

            if (response.Succ)
            {
                this.SetTokenCookie(response.Data.RefreshToken);
            }

            return (response);
        }

        /// <summary>
        /// Token检查
        /// </summary>
        /// <returns></returns>
        [HttpGet("tokens/check")]
        [Produces("application/json")]
        [ProducesResponseType(typeof(RespRet), 200)]
        [ProducesResponseType(401)]
        public RespRet CheckToken()
        {
            return new RespRet(true, "Pass");
        }
    }
}

